/*
============================================================================
 Name        : pd_file.cpp
 Author      : Jian(raphyer@hotmail.com)
 Version     :
 Copyright   : GPL
 Description : pd_file.cpp - source file
============================================================================
*/

// INCLUDE FILES
#include "pd_file.h"
#include "PdDefine.h"

#include <eikenv.h>
#include <f32file.h>
#include <bautils.h>


#define __USE_FS  (CEikonEnv::Static()->FsSession())

pd_file* pd_file_open(const DD_UNICODE* file_name, pd_file_mode mode) 
{
    TInt sMode    = 0 ;
    TBool replace = EFalse ;

    __DD_CHECK_PTR(file_name, DD_UNICODE, return NULL) ;

    if (mode == PD_FILE_CREATE || mode == PD_FILE_READ_WRITE) {
        sMode = EFileRead | EFileWrite ;
        replace = ETrue ;
    } else if (mode == PD_FILE_READ) {
        sMode = EFileRead ;
    } 

    sMode |= EFileShareAny; 

    RFile* sFile = NULL ;
    TPtrC fileName(__ToPtrC16(file_name)) ;

    TRAPD(
    err, 
    sFile = new(ELeave) RFile ;
    CleanupStack::PushL(sFile) ;
    LogLeaveIfError(replace ? sFile->Replace(__USE_FS, fileName, sMode) : sFile->Open(__USE_FS, fileName, sMode)) ;
    CleanupStack::Pop(sFile) ;
    ) ;

    if (err != KErrNone) {
        DD_LOG("pd_file_open open file = %S mode = %d, error = %d", file_name, mode, err) ;
        return NULL ;
    }

    return (pd_file*)sFile ;
}

void pd_file_close(pd_file* file) 
{
    __DD_ASSERT_DEFENSE(file, return) ;

    RFile* sFile = (RFile*)file ;
    sFile->Close() ;
    delete sFile ;
}

int pd_file_read(pd_file* file, void* ptr, DD_INT len) 
{
    __DD_ASSERT_DEFENSE(file && ptr && len > 0, return -1) ;

    RFile* sFile = (RFile*)file ;
    TPtr8 pData(__ToPtr8(ptr, len)) ;
    TInt err = KErrNone ;

    if ((err = sFile->Read(pData)) != KErrNone) {
        DD_LOG("pd_file_read read file ptr = %d, len = %d, error = %d", (DD_INT)ptr, len, err) ;
        return -1;
    }
    
    return pData.Length() ;
}

int pd_file_write(pd_file* file, void* ptr, DD_INT len) 
{
    __DD_ASSERT_DEFENSE(file && ptr && len > 0, return -1) ;

    RFile* sFile = (RFile*)file ;
    TInt err     = KErrNone ;

    if ((err = sFile->Write(__ToPtrC8Data(ptr, len))) != KErrNone) {
        DD_LOG("pd_file_write write file ptr = %d, len = %d, error = %d", (DD_INT)ptr, len, err) ;
        return -1;
    }
    
    return len ;
}

int pd_file_tell(pd_file* file) 
{
    __DD_ASSERT_DEFENSE(file, return -1) ;

    RFile* sFile = (RFile*)file ;

    TInt pos = 0 ;
    TInt err = KErrNone ;
    if ((err = sFile->Seek(ESeekCurrent, pos)) != KErrNone) {
        DD_LOG("pd_file_tell seek is err = %d", err) ;
        return -1;
    }

    return pos ;
}

int pd_file_seek(pd_file* file, DD_INT offset, pd_seek_mode mode) 
{
    __DD_ASSERT_DEFENSE(file, return -1) ;
    __DD_ASSERT_DEFENSE(mode != PD_FILE_BEGIN || offset >= 0, return 0) ;

    RFile* sFile = (RFile*)file ;

    TSeek sMode = ESeekStart;
    if (mode == PD_FILE_CURRENT)  sMode = ESeekCurrent ;
    else if (mode == PD_FILE_END) sMode = ESeekEnd ; 

    TInt pos = offset ;
    TInt err = KErrNone ;
    if ((err = sFile->Seek(sMode, pos)) != KErrNone) {
        DD_LOG("pd_file_seek seek file offset = %d, mood = %d, error = %d", offset, mode, err) ;
        return -1;
    }

    if (sMode == ESeekStart) 
        return pd_file_tell(file) ;

    return pos ;
}

int pd_file_flush(pd_file* file) 
{
    __DD_ASSERT_DEFENSE(file, return -1) ;

    RFile* sFile = (RFile*)file ;
    sFile->Flush() ;
    return 0 ;
}

int pd_file_size(pd_file* file) 
{
    __DD_ASSERT_DEFENSE(file, return -1) ;

    TInt size = 0 ;
    RFile* sFile = (RFile*)file ;
    sFile->Size(size) ;
    return size ;
}

DD_BOOL pd_file_exist(const DD_UNICODE* file_name) 
{
    __DD_CHECK_PTR(file_name, DD_UNICODE, return EFalse) ;

    TPtrC16 pName(__ToPtrC16(file_name)) ;
    if (pName.Length() > 0 && (pName[pName.Length() - 1] == '\\'))
        return DD_FALSE ;

    if (BaflUtils::FileExists(__USE_FS, pName))  return DD_TRUE ;

    return DD_FALSE ;
}

int pd_file_delete(const DD_UNICODE* file_name) 
{
    __DD_CHECK_PTR(file_name, DD_UNICODE, return EFalse) ;
    
    TPtrC16 pName(__ToPtrC16(file_name)) ;
    TInt err = BaflUtils::DeleteFile(__USE_FS, pName) ;

    if (err != KErrNone) {
        DD_LOG("pd_file_delete %S error = %d", file_name, err) ;
        return -1 ;
    }

    return 0 ;
}

/* End of File */
